#!/user/bin/env python
# -*- coding:utf-8 -*-
# author : 洛月
# email  : 2870093961@qq.com
# created: 2021-08-08 15:16
# updated: 2022-05-10 16:21
import requests
from bs4 import BeautifulSoup
from lxml.html import etree
import time
import random


class Proxy:
    class Headers:
        Windows = {
            "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                          "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36"}
        Linux = {
            "user-agent": "Mozilla/5.0 (X11; Linux x86_64) "
                          "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"}
        iPhone = {
            "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) "
                          "AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1"}
        Android = {
            "user-agent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) "
                          "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Mobile Safari/537.36"}

    class Response:
        Text = 1
        Json = 2
        Lxml = 3
        BeautifulSoup = 4
        Response = 5

    Hosts = {
        "本地": "http://192.168.1.10:9000"
    }

    def proxy_request(self, method, url, params=None, data=None, headers=None, cookies=None, timeout=None, verify=None,
                      retry=2, wait=0.5):
        """
        :param method: 请求方式
        :param url: 请求地址
        :param params: get参数
        :param data: post参数
        :param headers: 请求头
        :param cookies: cookies
        :param timeout: 请求超时限制
        :param verify: ssl验证
        :param retry: 重试次数
        :param wait: 重试等待时间
        :return: `Response <Response>`对象
        """
        # 随机选择代理服务器
        host = random.choice(list(self.Hosts.values()))
        print(f"使用代理：{host}")
        # 参数转为字典
        params = {
            "method": method, "url": url, "params": params, "data": data,
            "headers": headers, "cookies": cookies, "timeout": timeout,
            "verify": verify, "retry": retry, "wait": wait
        }
        # 检查重试次数和等待时间是否为默认值
        if retry == 2 and wait == 0.5:
            params.pop("retry")
            params.pop("wait")
        # 删除值为None的参数
        form = {key: val for key, val in params.items() if val is not None}
        # 请求
        for i in range(retry):
            try:
                res = requests.post(host, data=form, timeout=10)
                if res.status_code == 200:
                    return res
            except Exception as e:
                print(form, url, e)
                time.sleep(wait)
        return False

    def request(self, method, url, retry=2, wait=0.5, code=None, resp=None, **kwargs):
        """
        :param method: 请求方式
        :param url:  请求链接
        :param retry:重试次数
        :param wait: 重试等待时间
        :param code: 网页编码
        :param resp: 返回类型
        :param kwargs: 关键字参数
        :return: `Response <Response>`对象
        """
        for i in range(retry):
            try:
                res = requests.request(method, url, **kwargs)
                if res.status_code == 200:
                    return self.handle(res, code, resp)
            except Exception as err:
                print(method, url, err)
                time.sleep(wait)
        return False

    def get(self, url, params=None, retry=2, wait=0.5, code=None, resp=None, **kwargs):
        return self.request("GET", url, retry, wait, code, resp,
                            headers=self.Headers.Windows, params=params, **kwargs)

    def post(self, url, data=None, retry=2, wait=0.5, code=None, resp=None, **kwargs):
        return self.request("POST", url, retry, wait, code, resp,
                            headers=self.Headers.Windows, data=data, **kwargs)

    def proxy_get(self, url, code=None, resp=None, **kwargs):
        res = self.proxy_request("GET", url, **kwargs)
        return self.handle(html=res, code=code, resp=resp)

    def proxy_post(self, url, code=None, resp=None, **kwargs):
        res = self.proxy_request("POST", url, **kwargs)
        return self.handle(html=res, code=code, resp=resp)

    def handle(self, html, code, resp):
        if code is not None:
            html.encoding = code

        if resp == self.Response.Response or resp is None:
            return html
        elif resp == self.Response.BeautifulSoup:
            return BeautifulSoup(html.text, "lxml")
        elif resp == self.Response.Lxml:
            return etree.HTML(html.text)
        elif resp == self.Response.Text:
            return html.text
        elif resp == self.Response.Json:
            return html.json()
